#include "voltage.h"
#include "eeprom.h"
#include "tftp_server.h"
#include "wdg.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define VDDA                           ((uint32_t)3000)
#define VREFINT_CAL_ADD                 0x1FF80078
#define VDD_APPLI                      ((uint32_t)3300)    /* Value of analog voltage supply Vdda (unit: mV) */
#define RANGE_12BITS                   ((uint32_t)4095)    /* Max value with a full range of 12 bits */
#define TIMER_FREQUENCY_HZ             ((uint32_t)1000)    /* Timer frequency (unit: Hz). With SysClk set to 2MHz, timer frequency TIMER_FREQUENCY_HZ range is min=1Hz, max=33.3kHz. */

#define COMPUTATION_DIGITAL_12BITS_TO_VOLTAGE(ADC_DATA)                        \
  ( (ADC_DATA) * VDD_APPLI / RANGE_12BITS)

/* Private variables ---------------------------------------------------------*/
/* ADC handler declaration */
ADC_HandleTypeDef    AdcHandle;

static void ADC_Config(void)
{
    ADC_ChannelConfTypeDef   sConfig;
 
    AdcHandle.Instance = ADC1;
    
    AdcHandle.Init.OversamplingMode      = DISABLE;
    
    AdcHandle.Init.ClockPrescaler        = ADC_CLOCK_SYNC_PCLK_DIV1;
    AdcHandle.Init.LowPowerAutoPowerOff  = DISABLE;
    AdcHandle.Init.LowPowerFrequencyMode = ENABLE;
    AdcHandle.Init.LowPowerAutoWait      = DISABLE;
      
    AdcHandle.Init.Resolution            = ADC_RESOLUTION_12B;
    AdcHandle.Init.SamplingTime          = ADC_SAMPLETIME_7CYCLES_5;
    AdcHandle.Init.ScanConvMode          = ADC_SCAN_DIRECTION_FORWARD;
    AdcHandle.Init.DataAlign             = ADC_DATAALIGN_RIGHT;
    AdcHandle.Init.ContinuousConvMode    = DISABLE;
    AdcHandle.Init.DiscontinuousConvMode = DISABLE;
    AdcHandle.Init.ExternalTrigConvEdge  = ADC_EXTERNALTRIGCONVEDGE_NONE;
    AdcHandle.Init.EOCSelection          = ADC_EOC_SINGLE_CONV;
    AdcHandle.Init.DMAContinuousRequests = DISABLE;
   
    HAL_ADCEx_EnableVREFINT();
   
    HAL_ADC_DeInit(&AdcHandle);
    if (HAL_ADC_Init(&AdcHandle) != HAL_OK)
    {
      app_fault_handle(APP_VOLTAGE_ERROR);
    }
    
    if (HAL_ADCEx_Calibration_Start(&AdcHandle, ADC_SINGLE_ENDED) != HAL_OK)
    {
      app_fault_handle(APP_VOLTAGE_ERROR);
    }
 
     sConfig.Channel = ADC_CHANNEL_VREFINT;   
    
    if (HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK)
    {
      app_fault_handle(APP_VOLTAGE_ERROR);
    }
    
    if (HAL_ADC_Start_IT(&AdcHandle) != HAL_OK)
    {
      app_fault_handle(APP_VOLTAGE_ERROR);
    }
    
}

/**
* @brief  ADC MSP Init
* @param  hadc : ADC handle
* @retval None
*/
void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{    
  /* ADC1 Periph clock enable */
  __HAL_RCC_ADC1_CLK_ENABLE();
    
  HAL_NVIC_SetPriority(ADC1_COMP_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(ADC1_COMP_IRQn);
}

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
   __IO uint16_t  uhADCxConvertedValue = 0;
   __IO uint16_t  ADC_vrefint_value = 0;
   uint32_t  uhADCxConvertedVoltage = 0;
   eeprom_data_t eeprom_data;
 
    /*get vrefint*/
    ADC_vrefint_value = eeprom_read_half_word(VREFINT_CAL_ADD);
    /* Get the converted value of regular channel */
    uhADCxConvertedValue = HAL_ADC_GetValue(AdcHandle);
   
    uhADCxConvertedVoltage = (VDDA * ADC_vrefint_value) / uhADCxConvertedValue;
   
    eeprom_erase(1, EEPROM_VOLTAGE_ADDR);
   
    eeprom_data.len = 1;
    eeprom_data.address = EEPROM_VOLTAGE_ADDR;
    eeprom_data.eeprom_data = &uhADCxConvertedVoltage;
 
    eeprom_write(eeprom_data);
}

void get_voltage(void)
{
    ADC_Config();

}

static uint16_t read_voltage(uint8_t* buffer)
{
    *(uint32_t*)buffer = eeprom_read_word(EEPROM_VOLTAGE_ADDR);
 
    return 4;
}

bool _voltage_read_cmd_open(char* name, uint8_t mode)
{   
    if (mode != TFTP_RRQ) return false;
 
    if (0 == strcmp(name, "voltage.read")) {
        return true;
    } else {
        return false;
    }
}

uint16_t (_voltage_read_cmd_read)(uint8_t blk, uint8_t* buffer)
{
    if (blk >= 1) {
        return read_voltage(buffer);
    }else{
        return 0;
    }
}

void (_voltage_read_cmd_write)(uint8_t blk, uint8_t* buffer, uint16_t len)
{
     
}

void (_voltage_read_cmd_close)(void)
{

}

const tftp_server_plugin_t tftp_server_plugin_voltage_read_cmd = {
    _voltage_read_cmd_open,
    _voltage_read_cmd_read,
    _voltage_read_cmd_write,
    _voltage_read_cmd_close,
};


